#!/bin/bash

# change_to_txt 单元测试脚本

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[信息]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[警告]${NC} $1"
}

log_error() {
    echo -e "${RED}[错误]${NC} $1"
}

# 测试计数器
tests_passed=0
tests_failed=0

# 测试目录
TEST_DIR="/tmp/change_to_txt_test"
SCRIPT_PATH="../scripts/change_to_txt.sh"

# 创建测试环境
setup_test_env() {
    log_info "设置测试环境..."
    
    # 删除旧的测试目录（如果存在）
    rm -rf "$TEST_DIR"
    
    # 创建测试目录
    mkdir -p "$TEST_DIR"
    
    # 创建各种测试文件
    touch "$TEST_DIR/file1"           # 无扩展名文件
    touch "$TEST_DIR/file2.txt"       # 有扩展名文件
    touch "$TEST_DIR/file3.log"       # 有扩展名文件
    touch "$TEST_DIR/.hidden"         # 隐藏文件（无扩展名）
    touch "$TEST_DIR/.hidden.conf"    # 隐藏文件（有扩展名）
    
    # 创建嵌套目录
    mkdir -p "$TEST_DIR/subdir"
    touch "$TEST_DIR/subdir/file4"    # 子目录中的无扩展名文件
    touch "$TEST_DIR/subdir/file5.md" # 子目录中的有扩展名文件
    
    # 创建另一个嵌套目录
    mkdir -p "$TEST_DIR/subdir2/nested"
    touch "$TEST_DIR/subdir2/file6"        # 子目录中的无扩展名文件
    touch "$TEST_DIR/subdir2/nested/file7" # 深层嵌套目录中的无扩展名文件
    
    log_info "测试环境设置完成"
}

# 清理测试环境
teardown_test_env() {
    log_info "清理测试环境..."
    rm -rf "$TEST_DIR"
    log_info "测试环境清理完成"
}

# 运行单个测试
run_test() {
    local test_name="$1"
    local test_command="$2"
    local expected_exit_code="${3:-0}"
    
    log_info "运行测试: $test_name"
    
    # 运行测试命令
    eval "$test_command"
    local exit_code=$?
    
    # 检查退出码
    if [[ $exit_code -eq $expected_exit_code ]]; then
        log_info "测试通过: $test_name"
        ((tests_passed++))
    else
        log_error "测试失败: $test_name (期望退出码: $expected_exit_code, 实际退出码: $exit_code)"
        ((tests_failed++))
    fi
    
    echo ""
}

# 测试帮助信息
test_help() {
    run_test "帮助信息显示" "$SCRIPT_PATH --help" 0
    run_test "短帮助信息显示" "$SCRIPT_PATH -h" 0
}

# 测试无效目录路径
test_invalid_directory() {
    run_test "无效目录路径处理" "$SCRIPT_PATH /nonexistent/directory 2>/dev/null" 1
}

# 测试试运行模式
test_dry_run() {
    local count_before=$(find "$TEST_DIR" -type f ! -name "*.*" | wc -l)
    run_test "试运行模式" "$SCRIPT_PATH --dry-run "$TEST_DIR"" 0
    local count_after=$(find "$TEST_DIR" -type f ! -name "*.*" | wc -l)
    
    # 确保文件数量没有改变（因为是试运行）
    if [[ $count_before -eq $count_after ]]; then
        log_info "试运行模式测试通过: 文件数量未改变 ($count_before)"
        ((tests_passed++))
    else
        log_error "试运行模式测试失败: 文件数量改变了 ($count_before -> $count_after)"
        ((tests_failed++))
    fi
}

# 测试实际重命名
test_actual_rename() {
    # 在执行重命名前重新设置环境
    teardown_test_env
    setup_test_env
    
    local count_before=$(find "$TEST_DIR" -type f ! -name "*.*" ! -name ".*" | wc -l)
    local hidden_count_before=$(find "$TEST_DIR" -type f -name ".*" ! -name ".*.*" | wc -l)
    local total_count_before=$((count_before + hidden_count_before))
    
    run_test "实际重命名" "yes | $SCRIPT_PATH "$TEST_DIR"" 0
    
    local txt_count_after=$(find "$TEST_DIR" -type f -name "*.txt" | wc -l)
    
    # 检查是否正确重命名了文件
    if [[ $txt_count_after -ge $total_count_before ]]; then
        log_info "实际重命名测试通过: 至少 $total_count_before 个文件被重命名"
        ((tests_passed++))
    else
        log_error "实际重命名测试失败: 期望至少 $total_count_before 个文件被重命名，实际 $txt_count_after 个"
        ((tests_failed++))
    fi
}

# 测试详细输出
test_verbose() {
    run_test "详细输出模式" "yes | $SCRIPT_PATH --verbose "$TEST_DIR"" 0
}

# 测试跳过确认
test_skip_confirm() {
    run_test "跳过确认选项" "$SCRIPT_PATH --yes "$TEST_DIR"" 0
}

# 测试文件冲突处理
test_conflict_handling() {
    # 创建一个将要产生冲突的文件
    touch "$TEST_DIR/conflict"
    touch "$TEST_DIR/conflict.txt"
    
    run_test "文件冲突处理" "yes | $SCRIPT_PATH "$TEST_DIR"" 0
    
    # 检查冲突文件是否未被重命名
    if [[ -f "$TEST_DIR/conflict" && -f "$TEST_DIR/conflict.txt" ]]; then
        log_info "文件冲突处理测试通过: 冲突文件保持不变"
        ((tests_passed++))
    else
        log_error "文件冲突处理测试失败: 冲突文件被错误修改"
        ((tests_failed++))
    fi
}

# 测试隐藏文件处理
test_hidden_files() {
    # 在执行测试前重新设置环境
    teardown_test_env
    setup_test_env
    
    local hidden_no_ext_count=$(find "$TEST_DIR" -name ".*" ! -name ".*.*" ! -name "." | wc -l)
    
    run_test "处理隐藏文件" "yes | $SCRIPT_PATH "$TEST_DIR"" 0
    
    # 检查隐藏文件是否被正确处理
    local hidden_txt_count=$(find "$TEST_DIR" -name ".*.txt" | wc -l)
    
    if [[ $hidden_txt_count -ge 1 ]]; then
        log_info "隐藏文件处理测试通过: 至少 1 个隐藏文件被重命名"
        ((tests_passed++))
    else
        log_error "隐藏文件处理测试失败: 没有隐藏文件被重命名"
        ((tests_failed++))
    fi
}

# 运行所有测试
run_all_tests() {
    log_info "开始运行 change_to_txt 单元测试"
    echo ""
    
    setup_test_env
    
    test_help
    test_invalid_directory
    test_dry_run
    test_actual_rename
    test_verbose
    test_skip_confirm
    test_conflict_handling
    test_hidden_files
    
    teardown_test_env
    
    echo ""
    log_info "测试运行完成"
    echo "=================================="
    log_info "通过的测试: $tests_passed"
    log_info "失败的测试: $tests_failed"
    echo "=================================="
    
    if [[ $tests_failed -eq 0 ]]; then
        log_info "所有测试都通过了!"
        return 0
    else
        log_error "有 $tests_failed 个测试失败!"
        return 1
    fi
}

# 主函数
main() {
    # 检查脚本是否存在
    if [[ ! -f "$SCRIPT_PATH" ]]; then
        log_error "脚本文件不存在: $SCRIPT_PATH"
        exit 1
    fi
    
    # 添加执行权限
    chmod +x "$SCRIPT_PATH"
    
    # 运行所有测试
    run_all_tests
}

# 执行主函数
main "$@"